using Microsoft.ApplicationInspector.Logging;
using Microsoft.ApplicationInspector.RulesEngine;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Serilog.Events;
using Xunit;

namespace AppInspector.Tests.RuleProcessor;

public class ExtractSamplesTests
{
    

    private readonly ILoggerFactory _loggerFactory =
        new LogOptions { ConsoleVerbosityLevel = LogEventLevel.Verbose }.GetLoggerFactory();

    private ILogger _logger = new NullLogger<ExtractSamplesTests>();

    public ExtractSamplesTests()
    {
        _logger = _loggerFactory.CreateLogger<ExtractSamplesTests>();
    }

    const string shortTestString = "lorem ipsum dolor sit amet\nlorem ipsum dolor sit amet\nlorem ipsum dolor sit amet";
    // Two lines 1000 long
    const string longTestString = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
    // Two lines 1000 long and a 10 character line at end
    const string longTestStringShortThirdLine = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n1234567890";

    // The string is short, so we get the whole thing (clamped on both sides)
    [InlineData(shortTestString, 1,1,5,1,0,5,3,80)]
    [InlineData(shortTestString, 1, 3, 5, 3, 54, 5, 3, 80)]
    // These are 5 length at 0 index so we should only get context after (clamped on start)
    [InlineData(longTestString, 1, 1, 5, 1, 0, 5, 3, 305)]
    [InlineData(longTestString, 1, 1, 5, 1, 0, 5, 5, 505)]
    // Third line is 10 character, context is set to 500 (specified as 5 lines then multiplied by 100) so 500 before, 10 after (clamped on end)
    [InlineData(longTestStringShortThirdLine, 1, 3, 5, 3, 2000, 5, 5, 510)]

    [Theory]
    public void ExtractExcerptClampingTests(string testText, int StartCol, int StartLine, int EndCol, int EndLine, int Idx, int Length, int context, int expectedLength)
    {
        // Extract excerpt requires a text container
        var tc = new TextContainer(testText, "csharp", new Microsoft.ApplicationInspector.RulesEngine.Languages(_loggerFactory), _loggerFactory);
        var locStart = new Location() { Column = StartCol, Line = StartLine };
        var locEnd = new Location() { Column = EndCol, Line = EndLine };
        var boundary = new Boundary() { Index = Idx, Length = Length };
        var result = Microsoft.ApplicationInspector.RulesEngine.RuleProcessor.ExtractExcerpt(tc, locStart, locEnd, boundary, context);
        Assert.Equal(expectedLength, result.Length);
    }
}